【永井】 frontend_challenge_2 電気料金シュミレーションフォーム実装#75
【永井】 frontend_challenge_2 電気料金シュミレーションフォーム実装#75tsbs0514 wants to merge 29 commits intoenechange:masterfrom
Conversation
… manager detection
| ).toBeVisible(); | ||
|
|
||
| await expect(page.getByLabel("電力会社")).toBeVisible(); | ||
| await page.selectOption('select[name="powerCompany"]', "tokyo-electric"); |
There was a problem hiding this comment.
想定される選択肢として '東京電力' と 'その他' のみになっていることを確認するテストもあると、品質が高まり安心かと思います。
There was a problem hiding this comment.
ありがとうございます!
こちらで東京、関西それぞれoptionをチャックするテストを追加いたしました!
35597b0
| area = "out-of-service"; | ||
| isValid = false; | ||
| message = "サービスエリア対象外です。"; | ||
| } |
There was a problem hiding this comment.
エリアが今後増えることを考えると、else if を連ねるよりも、以下のように Record でマッピングしておく方が、可読性・保守性が高くなりそうです。
const areaMap: Record<string, PowerArea> = {
"1": "tokyo",
"5": "kansai",
};
const firstDigit = postalCode.charAt(0);
const area = areaMap[firstDigit] ?? "out-of-service";
const isValid = area !== "out-of-service";
const message = isValid ? "" : "サービスエリア対象外です。";
let を使うと変数の最終的な値を追うのが難しくなるため、できる限り const を使って、意図が明確な実装にすると良いと思います。
| {/* プラン */} | ||
| {watchedPowerCompany && !companyError && ( | ||
| <FormField label="プラン" labelHtmlFor="plan" required> | ||
| <Select |
There was a problem hiding this comment.
指定されたデザインのように、選択肢の説明文を実装する場合は、どのように実装する想定でしょうか?
もし設計方針などがあれば共有いただけると助かります。
There was a problem hiding this comment.
ありがとうございます!
すいません、こちら完全に漏れておりました。。。
下記で機能追加いたしました!
170782a
| <div className={cn("bg-gray-200 p-1 rounded-sm", className)}> | ||
| <input | ||
| type={type} | ||
| className={cn( |
There was a problem hiding this comment.
ありがとうございます!
デザイン上でSelectとInputのUIの高さに差異があったので、あえて差をつけていましたが、
おっしゃる通り一貫性保つ視点で考えると揃えた方が良いですね!
こちら対応いたしました!
26a7b4a
| const getAvailableCapacities = useCallback(() => { | ||
| if (!watchedPlan) return []; | ||
|
|
||
| switch (watchedPlan) { |
There was a problem hiding this comment.
こちらの switch 文についても、下記のように 選択肢の配列を定数として事前に定義し、
Record を使ってマッピングする形にリファクタしておくと、可読性・保守性が高まると思いました。
type CapacityOption = { value: ContractCapacity; label: string };
const tokyoJuryouBOptions: CapacityOption[] = [
"10A", "15A", "20A", "30A", "40A", "50A", "60A",
].map((amp) => ({ value: amp as const, label: amp }));
const juryouCKansaiOptions: CapacityOption[] = Array.from({ length: 44 }, (_, i) => {
const kva = i + 6;
const label = `${kva}kVA`;
return { value: label as ContractCapacity, label };
});
There was a problem hiding this comment.
ありがとうございます!
おっしゃる通りですね。。。!アドバイス基にリファクタしたらかなりスッキリしました!
勉強になります🙇
4d6c6e4
|
@tsbs0514 いくつかコメントをさせていただきましたので、無理のない範囲でご対応いただければと思います、よろしくお願いいたします! |
| `電力会社: ${data.powerCompany}\n` + | ||
| `プラン: ${data.plan}\n` + |
There was a problem hiding this comment.
結果画面の実装までしていただきありがとうございます!
一点だけコメントさせてください 🙇
電力会社やプランの表示について、現在は tokyo-electric のようなコードがそのまま表示されているようですので、東京電力や関西電力など、正式名称に変換して表示するとより分かりやすくなりそうです!
There was a problem hiding this comment.
ありがとうございます!
おっしゃる通りですね、、、確かにわかりづらいです💦
下記で定数モジュールを追加した際に修正いたしました!
f0ae55b
| // プラン変更時に契約容量をリセット | ||
| useEffect(() => { | ||
| resetField("contractCapacity"); | ||
| clearErrors("contractCapacity"); | ||
| }, [watchedPlan, resetField, clearErrors]); |
There was a problem hiding this comment.
プラン変更時に契約容量がリセットされますが、仕様通りとはいえ画面下部の結果確認ボタンが非活性のままになるため、ユーザーがエラーや未入力に気付きにくい可能性があります。
プラン変更後は、エラー表示などで再入力が必要であることを明示すると良さそうです!
2025-08-08.12.28.24.mov
There was a problem hiding this comment.
ありがとうございます!
おっしゃる通りですね!
下記で対応してみました!
47c1a1c#diff-23c2d9f0d06c5634220a6ad1b77122bc33e918102e28819a85752c5ee1caf2ddR44-R73
| const watchedPowerCompany = watch("powerCompany"); | ||
| const watchedPlan = watch("plan"); |
There was a problem hiding this comment.
ask
電力会社とプランに関しては、ElectricSimulationForm.tsxでも監視されていますが、ビジネスロジックとUI表示ロジックで分離させているなど、意図的なものでしょうか?
There was a problem hiding this comment.
なるほどですね、意図的であること承知しました。
また、細分化して整理までしていただきありがとうございます!
frontend_challenge_2/challenges/tsbs0514/src/hooks/useElectricForm.ts
Outdated
Show resolved
Hide resolved
|
|
||
| return currentArea === "tokyo" | ||
| ? [ | ||
| { value: "tokyo-electric" as const, label: "東京電力" }, |
There was a problem hiding this comment.
imo
型安全性は担保されているものの、選択肢の value やラベルを定数として切り出して一元管理すると、追加・変更に強く、再利用もしやすくなりそうですね!
プランや契約容量についても同様の対応ができそうです。
There was a problem hiding this comment.
ありがとうございます!
おっしゃる通り、ここの詰めが甘かったです。。。
下記で定数モジュールを追加し、全体的にリファクタいたしました!
f0ae55b
| description: | ||
| "現在の電気料金からどのくらいお得になるかチェック!郵便番号を入力するだけで簡単にシミュレーションできます。", | ||
| icons: { | ||
| icon: "https://enechange.jp/favicon.ico", |
There was a problem hiding this comment.
ファビコンが enechange のものに指定されていていいですね!細かいところまで実装いただきありがとうございます!
| /** | ||
| * 郵便番号からエリア判定 | ||
| * 静的エクスポート環境ではクライアントサイドで判定 | ||
| */ | ||
| export async function checkArea( |
There was a problem hiding this comment.
開発環境と本番環境で挙動を分ける実装にしていただきありがとうございます!
実際の運用環境を想定されている点、素晴らしいなと思いました 👍
|
お忙しい中、早急にご対応いただきありがとうございました! テストも充実しており、安心してレビューや動作確認を行うことができました。(実際に不具合等も見つかりませんでした 👍) また、ユーザーの操作性や心理面まで意識し、細部にまで配慮されたデザインのご提案もありがとうございます。 コメントへのご対応やご返信は、無理のない範囲で大丈夫です 🙇 引き続き、どうぞよろしくお願いいたします。 |
|
@ToruShimizu @kenji7157 |

電気料金シミュレーションアプリケーションの実装
概要
課題として開発した電気料金シミュレーションアプリケーションです。
ユーザーが郵便番号と電気使用状況を入力することで、電気料金のシミュレーション結果を提示します。
デモは GitHub Pages で確認できます。
主な機能
技術スタック
デザイン提案
使用ライブラリと選定理由
コアライブラリ
Next.js 15.4.5
React 19.1.0
TypeScript 5.x
フォーム管理
React Hook Form 7.62.0
Zod 4.0.14
@hookform/resolvers 5.2.1
スタイリング
Tailwind CSS 4.x
clsx 2.1.1
tailwind-merge 3.3.1
テスト
Jest 30.0.5
React Testing Library 16.3.0
Playwright 1.54.2
API モック
MSW 2.10.4
開発ツール
ESLint 9.x
ts-node 10.9.2
その他
react-icons 5.5.0
設計方針
useElectricFormフックで状態管理を集中セットアップ